package dp.gr03.payroll.application.commands;

import java.util.HashMap;

import dp.gr03.payroll.affiliationTransactions.ChangeMemberTransaction;
import dp.gr03.payroll.affiliationTransactions.ChangeUnaffiliatedTransaction;
import dp.gr03.payroll.classificationTransaction.ChangeCommissionTransaction;
import dp.gr03.payroll.classificationTransaction.ChangeHourlyTransaction;
import dp.gr03.payroll.classificationTransaction.ChangeSalariedTransaction;
import dp.gr03.payroll.exception.InvalidArgumentsException;
import dp.gr03.payroll.exception.PayRollException;
import dp.gr03.payroll.generalTransactions.ChangeAddressTransaction;
import dp.gr03.payroll.generalTransactions.ChangeNameTransaction;
import dp.gr03.payroll.methodTransactions.ChangeDirectTransaction;
import dp.gr03.payroll.methodTransactions.ChangeHoldTransaction;
import dp.gr03.payroll.methodTransactions.ChangeMailTransaction;
import dp.gr03.payroll.payrollApplication.Transaction;

public class ChangeEmployeeCommand implements TransactionParser
{
    protected HashMap<String, ChangeEmployeeTypeCommand> types;
    private int empId;
    private String value, value2;

    public ChangeEmployeeCommand()
    {
        types = new HashMap<String, ChangeEmployeeTypeCommand>();
        types.put("Name", new ChangeNameEmployee());
        types.put("Address", new ChangeAddressEmployee());
        types.put("Hourly", new ChangeHourlyBased());
        types.put("Salaried", new ChangeSalariedBased());
        types.put("Commissioned", new ChangeCommissionBased());
        types.put("Hold", new HoldPaycheck());
        types.put("Direct", new DirectPayckeck());
        types.put("Mail", new MailPaycheck());
        types.put("Member", new ChangeUnion());
        types.put("NoMember", new NoUnion());

    }

    @Override
    public String getActionString()
    {
        return "ChgEmp";
    }

    @Override
    public Transaction parse(String[] arguments) throws PayRollException
    {
        if (arguments.length >= 3)
        {
            empId = Integer.valueOf(arguments[1]);
            if (arguments[2].equals(""))
            {
                value = arguments[3];
            }
            if (!arguments[4].equals(""))
            {
                value2 = arguments[4];
            }

            ChangeEmployeeTypeCommand command = types.get(arguments[2]);
            if (command == null)
            {
                throw new PayRollException("This employee type doesn't exist.");
            }

            return command.createTransaction(arguments);
        } else
        {
            throw new InvalidArgumentsException("Not enough or invalid arguments supplied");
        }
    }

    private abstract class ChangeEmployeeTypeCommand
    {
        protected abstract Transaction createTransaction(String[] arguments) throws InvalidArgumentsException;
    }

    private class ChangeNameEmployee extends ChangeEmployeeTypeCommand
    {
        @Override
        protected Transaction createTransaction(String[] arguments)
        {
            return new ChangeNameTransaction(empId, value);
        }
    }

    private class ChangeAddressEmployee extends ChangeEmployeeTypeCommand
    {
        @Override
        protected Transaction createTransaction(String[] arguments)
        {
            return new ChangeAddressTransaction(empId, value);
        }
    }

    private class ChangeHourlyBased extends ChangeEmployeeTypeCommand
    {
        @Override
        protected Transaction createTransaction(String[] arguments)
        {
            return new ChangeHourlyTransaction(empId, Double.parseDouble(value));
        }
    }

    private class ChangeCommissionBased extends ChangeEmployeeTypeCommand
    {
        @Override
        protected Transaction createTransaction(String[] arguments)
        {
            return new ChangeCommissionTransaction(empId, Double.parseDouble(value2), Double.parseDouble(value));
        }
    }

    private class ChangeSalariedBased extends ChangeEmployeeTypeCommand
    {
        @Override
        protected Transaction createTransaction(String[] arguments)
        {
            return new ChangeSalariedTransaction(empId, Double.parseDouble(value));
        }
    }

    private class HoldPaycheck extends ChangeEmployeeTypeCommand
    {
        @Override
        protected Transaction createTransaction(String[] arguments)
        {
            return new ChangeHoldTransaction(empId);
        }
    }

    private class DirectPayckeck extends ChangeEmployeeTypeCommand
    {
        @Override
        protected Transaction createTransaction(String[] arguments)
        {
            return new ChangeDirectTransaction(empId, value, value2);
        }
    }

    private class MailPaycheck extends ChangeEmployeeTypeCommand
    {
        @Override
        protected Transaction createTransaction(String[] arguments)
        {
            return new ChangeMailTransaction(empId, value);
        }
    }

    private class ChangeUnion extends ChangeEmployeeTypeCommand
    {
        @Override
        protected Transaction createTransaction(String[] arguments)
        {
            return new ChangeMemberTransaction(empId, Integer.valueOf(value), Double.parseDouble(value2));
        }
    }

    private class NoUnion extends ChangeEmployeeTypeCommand
    {
        @Override
        protected Transaction createTransaction(String[] arguments)
        {
            return new ChangeUnaffiliatedTransaction(empId);
        }
    }
}
